﻿namespace NetFx.SMIL.References
{
  using System;
  using System.Text;
  using System.Collections;
  using System.Collections.Generic;

  using System.Reflection;
  using System.Reflection.Emit;
  using System.Runtime.InteropServices;

  using System.Diagnostics;
  using System.Diagnostics.CodeAnalysis;
  using System.Diagnostics.SymbolStore;
  using System.Security;
  using System.Security.Permissions;

  using NetFx.MSIL;

  /// <summary>
  /// 对模块的引用。
  /// </summary>
  public class ModuleRef:ReflectRef
  {
    #region Statics
    public new static ModuleRef it()
    {
      return new ModuleRef();
    }
    public static ModuleRef of(string identifier)
    {
      return new ModuleRef(identifier);
    }
    public static ModuleRef of(Module module)
    {
      return new ModuleRef(module);
    }
    #endregion
    #region Fields
    protected AssemblyRef assemblyRef = null;
    #endregion
    #region Properties
    /// <summary>
    /// 获取引用类型（为模块）。
    /// </summary>
    public override DefType ReflectionType
    {
      get { return DefType.Module; }
    }
    /// <summary>
    /// 获取反射信息。
    /// </summary>
    public virtual Module ReflectInfo
    {
      get
      {
        return this.referenced as Module;
      }
    }
    public override bool HasReflectInfo
    {
      get
      {
        return this.ReflectInfo != null;
      }
    }

    /// <summary>
    /// 获取模块所在的程序集。
    /// </summary>
    /// <remarks>
    /// 程序集是定位模块的必须部分，
    /// 为了准确定位模块，必须含有模块的程序集信息。
    /// </remarks>
    public virtual AssemblyRef Assembly
    {
      get
      {
        return this.assemblyRef;
      }
    }
    #endregion
    #region Constructors
    public ModuleRef() : base(null) { }
    public ModuleRef(string identifier) : base(identifier) { }
    public ModuleRef(string identifier,string assembly) : base(identifier) 
    {
      this.assemblyRef = AssemblyRef.of(assembly);
    }
    public ModuleRef(Module module)
      : base(String.Empty)
    {
      if (module != null)
      {
        this.identifier = module.Name;
        this.Bind(module);
      }
    }
    #endregion
    #region Methods
    protected override void Dispose(bool disposing)
    {
      if (disposing)
      {
        this.DisposeAssemblyRef();
      }
      base.Dispose(disposing);
    }
    protected override ReflectRef OnBinding(object source)
    {
      Module module = source as Module;
      if (module != null)
      {
        this.DisposeAssemblyRef();
        this.assemblyRef = AssemblyRef.of(module.Assembly);
      }
      return base.OnBinding(module);
    }
    protected override ReflectRef OnBreaking(object referenced)
    {
      if (this.Assembly != null)
      {
        this.Assembly.Break();
      }
      return base.OnBreaking(referenced);
    }
    protected virtual void DisposeAssemblyRef()
    {
      if (this.assemblyRef != null && !this.assemblyRef.IsDisposed)
      {
        this.assemblyRef.Dispose();
      }
      this.assemblyRef = null;
    }
    #endregion
  }
}
